/**
 * @description: deepClone
 * @author: huen2015
 */

function deepClone(obj: any, map: WeakMap<any, any> = new WeakMap()): any {
	if (obj == null || typeof obj !== 'object') return obj

	let result: any
	if (map.has(obj)) {
		result = map.get(obj)
		return result
	}

	if (obj instanceof Array) {
		result = []
		obj.forEach((item: any) => {
			const cloneValue = deepClone(item, map)
			result.push(cloneValue)
		})
	} else if (obj instanceof Set) {
		result = new Set()
		obj.forEach((item: any) => {
			const cloneValue = deepClone(item, map)
			result.add(cloneValue)
		})
	} else if (obj instanceof Map) {
		result = new Map()
		for (let [key, value] of obj) {
			const cloneKey = deepClone(key, map)
			const cloneValue = deepClone(value, map)
			result.set(cloneKey, cloneValue)
		}
	} else if (obj instanceof Object) {
		result = {}
		for (const key in obj) {
			const cloneKey = deepClone(key, map)
			const cloneValue = deepClone(obj[key], map)
			result[cloneKey] = cloneValue
		}
	}

	map.set(obj, result)
	return result
}

// 功能测试
const a: any = {
	map: new Map([
		['a', '1'],
		['b', '2'],
	]),
	set: new Set([1, 2, 3, 3]),
	array: [11, 2, 22],
	object: { test: '12' },
	null: null,
	undefined: undefined,
}
a.self = a.set
const result = deepClone(a)
console.info('deepClone', result)

export { deepClone }
